<?php
/**
 * SimpleDB emulator in XML (PHP Port)
 *  by Shashank Shekhar
 * Revisions:
 *  1. August 31, 2009 - Completed first draft implementation
 *
*/

/* Just a utility function, can be removed */
function debug_r( $d, $e=0 ) {
	echo "<pre>".print_r( $d , 1)."</pre>";
	if( $e ) exit;
}

/**
 * Encapsulates the functionalities of the SimpleDB interface.
 * This API doesn't follow the Request/Response model used by the SimpleDB PHP Library.
 * It just allows you to emulate the kind of schema-less storage SimpleDB provides.
 * A SimpleDB API-compliant version can be written in order to use this class for testing
 * your applications offline without using the real SimpleDB server.
 *
 */
class SimpleDB {
	private $doc;
	private $xpath;
	
	function __construct() {
		$this->doc = new DOMDocument();
	}
	
	function __destruct() {
		$this->close();
	}
	
	public function open($connectionString = "") {
		$this->doc->load("simpleDB.xml");
		$this->xpath = new DOMXPath($this->doc);
	}
	
	public function close() {
		$this->doc->save("simpleDB.xml");
	}
	
	/* API Methods */
	public function CreateDomain($domainName) {
		if ($this->xpath->query('//domains/domain[name = "'.$domainName.'"]')->length > 0)
			return FALSE;
		$newNode = $this->doc->createElement("domain");
		$newNode->appendChild($this->doc->createElement("name", $domainName));
        $this->doc->getElementsByTagName("domains")->item(0)->appendChild($newNode);
	}
	
	
	public function DeleteDomain($domainName) {
		$item = $this->xpath->query('//domains/domain[name = "'.$domainName.'"]');
		if ($item->length == 0) return;
		$this->doc->documentElement->removeChild($item->item(0));
	}
	
	/* TODO: Make a common ListDomains() method for all */
	public function ListDomainsNT($maxNumberOfDomains, $nextToken) {
		$list = array();
		$i = 0;
		foreach($this->doc->documentElement->childNodes as $node) {
			if ($i++ == $maxNumberOfDomains) break;
			$list[] = $node->getElementsByTagName("name")->item(0)->nodeValue;
		}
		return $list;
	}
	
	
	public function ListDomainsT($nextToken) {
		
	}
	
	
	public function ListDomains() {
		return $this->ListDomainsNT(-1, "");
	}
	
	
	public function PutAttributes($domainName, $itemName, $attributes) {
		if (sizeof($attributes) == 0) return;
		
		$domain = $this->xpath->query("//domains/domain[name = \"$domainName\"]")->item(0);
		if ($this->xpath->query("//domains/domain[name = \"$domainName\"]/item[name = \"$itemName\"]")->length == 0) { // have to create the item node
			$newItem = $this->doc->createElement("item");
			$newItem->appendChild($this->doc->createElement("name", $itemName));
			$newAttributes = $newItem->appendChild($this->doc->createElement("attributes"));
			foreach ($attributes as $key => $value) {
				$key = trim($key);
				$newAttributes->appendChild($this->doc->createElement($key, $value));
			}
			$newDomain = $domain->appendChild($newItem);
		} else {
			$itemAttribs = $this->xpath->query("//domains/domain[name = \"$domainName\"]/item[name = \"$itemName\"]/attributes")->item(0);
			foreach ($attributes as $key => $value) {
				$key = trim($key);
				if ($itemAttribs->getElementsByTagName($key)->length == 0) {
					$itemAttribs->appendChild($this->doc->createElement($key, $value));
				} else {
					$itemAttribs->replaceChild($this->doc->createElement($key, $value), $itemAttribs->getElementsByTagName($key)->item(0));
				}
			}
		}
	}
	
	
	public function GetAttributes($domainName, $itemName, $attributeNames) {
		$attributes = array();
		foreach ($attributeNames as $key) {
			$key = trim($key);
			$item = $this->xpath->query("//domains/domain[name = \"$domainName\"]/item[name = \"$itemName\"]/attributes/$key");
			if ($item->length != 0)
				$attributes[$key] = $item->item(0)->nodeValue;
		}
		return $attributes;
	}
	
	/*
	public function DeleteAttributes($domainName, $itemName, $float[] attributes) {
	
	}*/
	
	/* TODO: Make a common DeleteAttributes() method for all */
	public function DeleteAttributesDIA($domainName, $itemName, $attributeNames) {
		$itemAttribs = $this->xpath->query("//domains/domain[name = \"$domainName\"]/item[name = \"$itemName\"]/attributes");
		if ($itemAttribs->length == 0) return;
		foreach ($attributeNames as $key) {
			if (sizeof($n = $itemAttribs->item(0)->getElementsByTagName($key)) > 0)
				$itemAttribs->item(0)->removeChild($n->item(0));
		}
		if ($itemAttribs->item(0)->childNodes->length == 0)
			$itemAttribs->item(0)->parentNode->parentNode->removeChild($itemAttribs->item(0)->parentNode);
	}
	
	
	public function DeleteAttributesDI($domainName, $itemName) {
		$item = $this->xpath->query("//domains/domain[name = \"$domainName\"]/item[name = \"$itemName\"]");
		if ($item->length == 0) return;
		$item->item(0)->parentNode->removeChild($item->item(0));
	}
	
	/* TODO: Make a common Query() method for all */
	public function QueryDNT($domainName, $maxNumberOfItems, $nextToken) {
		
	}
	
	
	public function QueryDT($domainName, $nextToken) {
		
	}
	
	
	public function QueryDQNT($domainName, $query, $maxNumberOfItems, $nextToken) {
		
	}
	
	
	public function QueryDQT($domainName, $query, $nextToken) {
		
	}
	
	
	public function QueryDQ($domainName, $query) {
		
	}
}
?>